package com.zboot.zbootadmin.project.system.menu.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zboot.zbootadmin.common.constant.HttpStatus;
import com.zboot.zbootadmin.common.domain.ResponseData;
import com.zboot.zbootadmin.common.security.service.TokenService;
import com.zboot.zbootadmin.common.utils.ServletUtils;
import com.zboot.zbootadmin.common.utils.StringUtils;
import com.zboot.zbootadmin.project.system.menu.entity.SysMenu;
import com.zboot.zbootadmin.project.system.menu.entity.vo.MenuVo;
import com.zboot.zbootadmin.project.system.menu.entity.vo.MetaVo;
import com.zboot.zbootadmin.project.system.menu.entity.vo.RouterVo;
import com.zboot.zbootadmin.project.system.menu.mapper.SysMenuMapper;
import com.zboot.zbootadmin.project.system.menu.service.SysMenuService;
import com.zboot.zbootadmin.project.system.user.domain.SysUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 菜单权限表 服务实现类
 * </p>
 *
 * @author zyt
 * @since 2020-07-18
 */
@Service
@Slf4j
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {

    @Autowired
    private SysMenuMapper sysMenuMapper;

    @Autowired
    private TokenService tokenService;

    List<SysMenu> sysMenusRecursion = new ArrayList<>();

    /**
     *
     * @Description: 循环添加菜单
     *
     * @author: zyt
     * @date: 22:24 2020/9/7
     * @param: [parentId, menus]
     * @return: java.util.List<com.zboot.zbootadmin.project.system.menu.entity.SysMenu>
     *
     */
    @Override
    public List<SysMenu> getMenuList(Long parentId, List<SysMenu> menus) {
        List<SysMenu> menutree = new ArrayList<SysMenu>();
        menus.stream().forEach(tree->{
            if (parentId.longValue()==tree.getParentId()) {
                menutree.add(tree);
            }
        });
        menutree.stream().forEach(action->{
            /*action.setChildren(getChildren(action.getMenuId(),menus));*/
            action.setChildren(getMenuList(action.getMenuId(),menus));
        });

        return menutree;
    }

   /* @Override
    public List<SysMenu> getChildren(Long id, List<SysMenu> menus) {
        List<SysMenu> childList = new ArrayList<SysMenu>();
        menus.stream().forEach(child->{
            if (id.longValue()==child.getParentId()) {
                childList.add(child);
            }
        });
        childList.stream().forEach(action->{
            action.setChildren(getChildren(action.getMenuId(),menus));
        });

        if (childList.size()==0) {
            return new ArrayList<SysMenu>();
        }
        return childList;
    }*/

   /**
    *
    * @Description: 构建路由
    *
    * @author: zyt
    * @date: 22:25 2020/9/7
    * @param: [menus]
    * @return: java.util.List<com.zboot.zbootadmin.project.system.menu.entity.vo.RouterVo>
    *
    */
    @Override
    public List<RouterVo> buildMenu(List<SysMenu> menus) {

        List<RouterVo> routers = new LinkedList<RouterVo>();
        menus.stream().forEach(menu->{
            RouterVo routerVo = new RouterVo();
            routerVo.setName(StringUtils.capitalize(menu.getPath()));
            routerVo.setPath(getRouterPath(menu));
            routerVo.setComponent(StringUtils.isEmpty(menu.getComponent()) ? "Layout" : menu.getComponent());
            routerVo.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon()));
            routerVo.setMenuId(menu.getMenuId());
            routerVo.setParentId(menu.getParentId());
            routerVo.setHidden("0".equals(menu.getVisible())?false:true);
            List<SysMenu> cMenus = menu.getChildren();
            if (cMenus!=null && !cMenus.isEmpty() && cMenus.size() > 0 && "C".equals(menu.getMenuType()))
            {
                routerVo.setAlwaysShow(true);
                routerVo.setRedirect("noRedirect");
                routerVo.setChildren(buildMenu(cMenus));
            }
            routers.add(routerVo);

        });
        routers.stream().forEach(route->{
            if (route.getParentId().longValue()==0 && route.getChildren()==null) {

                route.setPath(route.getPath());
                route.setRedirect(route.getPath()+route.getPath());

                RouterVo routerVo = new RouterVo();
                List<RouterVo> routerVoList = new ArrayList<>();
                routerVo.setName(route.getName());
                routerVo.setPath(route.getPath()+route.getPath());
                routerVo.setHidden(route.getHidden());
                routerVo.setComponent(route.getComponent());
                routerVo.setAlwaysShow(true);
                routerVo.setMeta(route.getMeta());
                routerVo.setMenuId(route.getMenuId());
                routerVo.setParentId(route.getParentId());
                routerVoList.add(routerVo);
                route.setChildren(routerVoList);

                route.setName(route.getPath().replace("/",""));
                route.setComponent("Layout");
            }

        });
        return routers;
    }



    /**
     * 获取路由地址
     *
     * @param menu 菜单信息
     * @return 路由地址
     */
    public String getRouterPath(SysMenu menu)
    {
        String routerPath = menu.getPath();
        // 非外链并且是一级目录
        if (0 == menu.getParentId() && 1==menu.getIsFrame())
        {
            routerPath = "/" + menu.getPath();
        }
        return routerPath;
    }

    /**
     *
     * @Description: 获取所有才菜单
     *
     * @author: zyt
     * @date: 22:25 2020/9/7
     * @param: []
     * @return: java.util.List<com.zboot.zbootadmin.project.system.menu.entity.SysMenu>
     *
     */
    @Override
    public List<SysMenu> selectMenuList() {
        return sysMenuMapper.selectMenuList();
    }

    /**
     *
     * @Description: 此方法为删除菜单所有，递归父级以下菜单，不包括父级菜单
     *
     * @author: zyt
     * @date: 22:26 2020/9/7
     * @param: [menu, parentId]
     * @return: java.util.List<com.zboot.zbootadmin.project.system.menu.entity.SysMenu>
     *
     */
    @Override
    public List<SysMenu> queryByParentId(SysMenu menu,Long parentId) {

        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("parent_id",menu.getMenuId());
        List<SysMenu> sysMenu = this.list(queryWrapper);
        if (sysMenu!=null) {
            sysMenu.stream().forEach(menuObj->{
                sysMenusRecursion.add(menuObj);
                sysMenu.stream().forEach(m->queryByParentId(m,m.getParentId()));
            });
        }

        return sysMenusRecursion;

    }

    @Override
    public List<SysMenu> selectMenuListByUserId(String userId) {

        return sysMenuMapper.selectMenuListByUserId(userId);
    }


    @Override
    @Transactional
    public void addMenu(SysMenu sysMenu) {
        SysUser user = tokenService.getLoginUser(ServletUtils.getRequest()).getUser();
        sysMenu.setCreateBy(user.getUserName());
        sysMenu.setCreateTime(new Date());
        sysMenu.setUpdateTime(new Date());
        sysMenu.setUpdateBy(user.getUserName());
        sysMenu.setStatus("0");
        sysMenu.setVisible("0");
        if ("B".equals(sysMenu.getMenuType())) {
            SysMenu menuObj = getById(sysMenu.getMenuId());
            sysMenu.setParentId(menuObj.getMenuId());
            sysMenu.setMenuId(null);
        }
        if ( sysMenu.getParentId()!=null && sysMenu.getMenuId()!=null && sysMenu.getParentId().longValue()==0 && sysMenu.getMenuId().longValue()!=0){
            //  二级菜单
            SysMenu menuObj = getById(sysMenu.getMenuId());
            menuObj.setMenuType("C");
            menuObj.setComponent("");
            saveOrUpdate(menuObj);

            sysMenu.setParentId(menuObj.getMenuId());
            sysMenu.setMenuId(null);

        }
        if (  sysMenu.getParentId()!= null &&  sysMenu.getMenuId()!=null && sysMenu.getParentId().longValue()!=0 && sysMenu.getMenuId().longValue()!=0) {
            //  三级菜单及以上
            SysMenu menuObj = getById(sysMenu.getMenuId());
            menuObj.setMenuType("C");
            saveOrUpdate(menuObj);

            sysMenu.setParentId(menuObj.getMenuId());
            sysMenu.setMenuId(null);
        }
        save(sysMenu);

    }

    @Override
    public List<MenuVo> showMenuList(List<SysMenu> menus) {
        List<MenuVo> menuVos = menus.stream().map(MenuVo::new).collect(Collectors.toList());
        return menuVos;
    }

    @Override
    public Set<String> selectMenuPermsByUserId(Long userId) {
        List<String> perms = sysMenuMapper.selectMenuPermsByUserId(userId);
        Set<String> permsSet = new HashSet<>();
        for (String perm : perms)
        {
            if (StringUtils.isNotEmpty(perm))
            {
                permsSet.addAll(Arrays.asList(perm.trim().split(",")));
            }
        }
        return permsSet;
    }
}
